package br.com.puertorico.common.utils;

/**
 * D&iacute;gito verificador ou algarismo de controle &eacute; um mecanismo de
 * autentica&ccedil;&atilde;o utilizado para verificar a validade e a
 * autenticidade de um valor num&eacute;rico, evitando dessa forma fraudes ou
 * erros de transmiss&atilde;o ou digita&ccedil;&atilde;o.
 *
 * @author daniel
 *
 */
public class DigitoVerificadorUtils {

	/**
	 * Conforme o esquema abaixo, para calcular o primeiro d&iacute;gito
	 * verificador, cada d&iacute;gito do n&uacute;mero, come&ccedil;ando da
	 * direita para a esquerda (do d&iacute;gito menos significativo para o
	 * d&iacute;gito mais significativo) &eacute; multiplicado, na ordem, por 2,
	 * depois 3, depois 4 e assim sucessivamente, at&eacute; o primeiro
	 * d&iacute;gito do n&uacute;mero. O somat&oacute;rio dessas
	 * multiplica&ccedil;&otilde;es &eacute; multiplicado por 10 e dividida por
	 * 11. O resto desta divis&atilde;o (m&oacute;dulo 11) &eacute; o primeiro
	 * d&iacute;gito verificador. Para calcular o pr&oacute;ximo d&iacute;gito,
	 * considera-se o d&iacute;gito anterior como parte do n&uacute;mero e
	 * efetua-se o mesmo processo. No exemplo, foi considerado o n&uacute;mero
	 * 261533:
	 *
	 * <pre>
	 * +---+---+---+---+---+---+   +---+
	 *   | 2 | 6 | 1 | 5 | 3 | 3 | - | 9 |<---
	 *   +---+---+---+---+---+---+   +---+
	 *     |   |   |   |   |   |
	 *     x7  x6  x5  x4  x3  x2
	 *     |   |   |   |   |   |
	 *     =14 =36 =5  =20 =9  =6
	 *     +---+---+---+---+---+-> = (90 x 10) / 11 = 81, resto 9 => D&iacute;gito = 9
	 *
	 *   +---+---+---+---+---+---+   +---+---+
	 *   | 2 | 6 | 1 | 5 | 3 | 3 | - | 9 | 4 |<---
	 *   +---+---+---+---+---+---+   +---+---+
	 *     |   |   |   |   |   |       |
	 *     x8  x7  x6  x5  x4  x3      x2
	 *     |   |   |   |   |   |       |
	 *     =16 =42 =6  =25 =12 =9      =18
	 *     +---+---+---+---+---+-> = (128 x 10) / 11 = 116, resto 4 => D&iacute;gito = 4
	 * </pre>
	 *
	 * Considerando o n&uacute;mero 2615337, onde o 7 &eacute; o d&iacute;gito
	 * verificador e a valida&ccedil;&atilde;o &eacute; atrav&eacute;s do
	 * &quot;m&oacute;dulo 11&quot;. N&atilde;o seria considerado um
	 * n&uacute;mero v&aacute;lido, pois o n&uacute;mero correto &eacute;
	 * 2615339, onde 9 &eacute; o d&iacute;gito verificador gerado pelo
	 * m&oacute;dulo 11.
	 * <p>
	 * <strong>OBS:</strong> Caso o resto seja <strong>10</strong> o
	 * d&iacute;gito verificador ser&aacute; <strong>0</strong>.
	 * </p>
	 *
	 * @param s
	 * @return
	 */
	public static String adicionaModulo11(String s) {
		Integer soma = 0;
		Integer multiplicador = s.length() + 1;
		for (char c : s.toCharArray()) {
			soma += Integer.parseInt(Character.toString(c)) * multiplicador--;
		}

		Integer mod = (soma * 10) % 11;
		if (mod == 10) {
			mod = 0;
		}

		return s + mod.toString();
	}

	/**
	 * Verifica se o d&iacute;gito verificador corresponde ao valor
	 * n&uacute;merico.
	 *
	 * @return
	 */
	public static boolean validaModulo11(String valorNumerico) {
		String str = valorNumerico.substring(0, valorNumerico.length() - 1);
		System.out.println(str);
		String comModulo = adicionaModulo11(str);
		return comModulo.equals(valorNumerico);
	}

}